package com.fourmob.datetimepicker.util;
/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.StackLayout;
import ohos.app.Context;

/**
 * ViewAnimator
 *
 * @since 2021-04-12
 */
public class ViewAnimator extends StackLayout {

    int mWhichChild = 0;
    boolean mFirstTime = true;
    boolean mAnimateFirstTime = true;
    boolean mMeasureAllChildren = true;
    AnimatorValue mInAnimation;
    AnimatorValue mOutAnimation;

    public ViewAnimator(Context context) {
        super(context);
    }

    public ViewAnimator(Context context, AttrSet attrSet) {
        super(context, attrSet);
        initViewAnimator(context, attrSet);
    }

    public AnimatorValue getInAnimation() {
        return mInAnimation;
    }

    public void setInAnimation(AnimatorValue mInAnimation) {
        this.mInAnimation = mInAnimation;
    }

    public AnimatorValue getOutAnimation() {
        return mOutAnimation;
    }

    public void setOutAnimation(AnimatorValue mOutAnimation) {
        this.mOutAnimation = mOutAnimation;
    }

    private void initViewAnimator(Context context, AttrSet attrs) {
        if (attrs == null) {
            // For compatibility, always measure children when undefined.
            mMeasureAllChildren = true;
            return;
        }
    }

    /**
     * Returns the index of the currently displayed child view.
     *
     * @return int类型
     */
    public int getDisplayedChild() {
        return mWhichChild;
    }

    /**
     * Manually shows the next child.
     */

    public void showNext() {
        setDisplayedChild(mWhichChild + 1);
    }

    /**
     * Manually shows the previous child.
     */

    public void showPrevious() {
        setDisplayedChild(mWhichChild - 1);
    }

    void showOnly(int childIndex, boolean animate) {
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            final Component child = getComponentAt(i);
            if (i == childIndex) {
                if (animate && mInAnimation != null) {
                    mInAnimation.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                        @Override
                        public void onUpdate(AnimatorValue animatorValue, float v) {
                            child.setContentPosition(child.getContentPositionX(), child.getContentPositionY());
                        }
                    });
                    mInAnimation.start();
                }
                child.setVisibility(Component.VISIBLE);
                mFirstTime = false;
            } else {
                if (animate && mOutAnimation != null && child.getVisibility() == Component.VISIBLE) {
                    mOutAnimation.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                        @Override
                        public void onUpdate(AnimatorValue animatorValue, float v) {
                            child.setContentPosition(child.getContentPositionX(), child.getContentPositionY());
                        }
                    });
                    mOutAnimation.start();
                }
                child.setVisibility(Component.HIDE);
            }
        }
    }

    void showOnly(int childIndex) {
        final boolean animate = !mFirstTime || mAnimateFirstTime;
        showOnly(childIndex, animate);
    }

    @Override
    public void addComponent(Component child, int index, ComponentContainer.LayoutConfig layoutConfig) {
        super.addComponent(child, index, layoutConfig);
        if (getChildCount() == 1) {
            child.setVisibility(Component.VISIBLE);
        } else {
            child.setVisibility(Component.HIDE);
        }
        if (index >= 0 && mWhichChild >= index) {
            // Added item above current one, increment the index of the displayed child
            setDisplayedChild(mWhichChild + 1);
        }
    }

    @Override
    public void removeComponent(Component component) {
        super.removeComponent(component);
        final int index = getChildIndex(component);
        if (index >= 0) {
            removeComponentAt(index);
        }
    }

    @Override
    public void removeComponentAt(int index) {
        super.removeComponentAt(index);
        final int childCount = getChildCount();
        if (childCount == 0) {
            mWhichChild = 0;
            mFirstTime = true;
        } else if (mWhichChild >= childCount) {
            // Displayed is above child count, so float down to top of stack
            setDisplayedChild(childCount - 1);
        } else if (mWhichChild == index) {
            // Displayed was removed, so show the new child living in its place
            setDisplayedChild(mWhichChild);
        }
    }

    @Override
    public void removeAllComponents() {
        super.removeAllComponents();
        mWhichChild = 0;
        mFirstTime = true;
    }

    public void removeViewInLayout(Component view) {
        removeComponent(view);
    }

    @Override
    public void removeComponents(int start, int count) {
        super.removeComponents(start, count);
        if (getChildCount() == 0) {
            mWhichChild = 0;
            mFirstTime = true;
        } else if (mWhichChild >= start && mWhichChild < start + count) {
            // Try showing new displayed child, wrapping if needed
            setDisplayedChild(mWhichChild);
        }
    }

    @Override
    public String getAccessibilityDescription() {
        return ViewAnimator.class.getName();
    }

    public void removeViewsInLayout(int start, int count) {
        removeComponents(start, count);
    }

    /**
     * Returns the View corresponding to the currently displayed child.
     *
     * @return The View currently displayed.
     * @see #getDisplayedChild()
     */
    public Component getCurrentView() {
        return getComponentAt(mWhichChild);
    }

    public boolean getAnimateFirstView() {
        return mAnimateFirstTime;
    }

    /**
     * Indicates whether the current View should be animated the first time
     * the ViewAnimator is displayed.
     *
     * @param animate True to animate the current View the first time it is displayed,
     * false otherwise.
     */
    public void setAnimateFirstView(boolean animate) {
        mAnimateFirstTime = animate;
    }

    public void setDisplayedChild(int whichChild) {
        mWhichChild = whichChild;
        if (whichChild >= getChildCount()) {
            mWhichChild = 0;
        } else if (whichChild < 0) {
            mWhichChild = getChildCount() - 1;
        }
        boolean hasFocus = getComponentAt(mWhichChild) != null;

        // This will clear old focus if we had it
        showOnly(mWhichChild);
        if (hasFocus) {
            // Try to retake focus if we had it
            requestFocus();
        }
    }
}
